package com.yuou.shiro;


import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;

import com.yuou.model.Bloger;
import com.yuou.model.BlogerRole;
import com.yuou.model.Role;
import com.yuou.service.BlogerRoleService;
import com.yuou.service.BlogerService;
import com.yuou.service.MenuService;
import com.yuou.service.RoleService;

public class ShiroDbRealm extends AuthorizingRealm {
	@Resource(name = "blogerServiceImpl")
	private BlogerService blogerService;
	
	@Resource(name = "menuServiceImpl")
	private MenuService menuService;
	
	@Resource(name = "roleServiceImpl")
	private RoleService roleService;
	
	@Resource(name = "blogerRoleServiceImpl")
	private BlogerRoleService blogerRoleService;

	public ShiroDbRealm() {
		super();
	}

	/**
	 * 验证登陆
	 */
	@Override
	protected synchronized AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		Bloger bloger = blogerService.getUserByLoginName(token.getUsername());
		if (bloger != null && bloger.getStatus()==1) {
			return new SimpleAuthenticationInfo(bloger, bloger.getPassword(), getName());
		}else if (bloger.getStatus() == 2) {// 账号冻结
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        } else {
			throw new AuthenticationException();
		}
	}

	/**
	 * 登陆成功之后，进行角色和权限验证
	 */
	  @Override
	  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		  SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		  Set<String> permsSet = null ;
		  try {
	          //这里应该根据userName使用role和permission 的serive层来做判断，并将对应的权限加进来，下面简化了这一步
	    		
	    		Bloger bloger = (Bloger) getAvailablePrincipal(principals);
	    		BlogerRole blogerRole = blogerRoleService.selectByblogerId(bloger.getId());
	    		Role role = roleService.selectByPrimaryKey(blogerRole.getRoleId());
	    		if(role!=null) {
	    			if(role.getStatus()==1) {
	    				// 列举此用户所有的权限
	    				permsSet = menuService.listPerms(blogerRole.getRoleId());
	    				//for(String perms : permsSet) {
	    					//System.out.println(perms);
	    				//}
	    			}
	    		}
	    		
	    		if(permsSet!=null) {
	    			authorizationInfo.addStringPermissions(permsSet);
	    		}
	    		return authorizationInfo;
	        }catch(Exception e){
	            e.printStackTrace();
	        }
		return authorizationInfo;
		
	  }
	 

	/**
	 * 清除所有用户授权信息缓存.
	 */
	public void clearCachedAuthorizationInfo(String principal) {
		SimplePrincipalCollection principals = 
							new SimplePrincipalCollection( principal, getName());
		clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除所有用户授权信息缓存.
	 */
	public void clearAllCachedAuthorizationInfo() {
		Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
		if (cache != null) {
			for (Object key : cache.keys()) {
				cache.remove(key);
			}
		}
	}

	 /*@PostConstruct
	 public void initCredentialsMatcher() {//MD5鍔犲瘑
	 HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(ALGORITHM);
	 setCredentialsMatcher(matcher);
	 }*/
 	/**
	 * 
	 * @Title: clearAuthz 
	 * @Description: 清除缓存的授权信息  
	 * @return void    返回类型
	 */
	public void clearAuthz(){
		this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
	}

}